{
 "cells": [
  {
   "cell_type": "code",
   "id": "initial_id",
   "metadata": {
    "collapsed": true,
    "ExecuteTime": {
     "end_time": "2025-01-03T07:18:38.202737Z",
     "start_time": "2025-01-03T07:18:38.195736Z"
    }
   },
   "source": [
    "import tensorflow as tf\n",
    "import numpy as np\n",
    "from sklearn.datasets import fetch_california_housing\n",
    "from sklearn.preprocessing import StandardScaler\n",
    "from sklearn.model_selection import train_test_split\n",
    "import warnings"
   ],
   "execution_count": 6,
   "outputs": []
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-03T07:20:18.488889Z",
     "start_time": "2025-01-03T07:18:38.866341Z"
    }
   },
   "cell_type": "code",
   "source": [
    "\n",
    "# TensorFlow为我们去计算梯度，但是同时也给了我们更方便的求解方式\n",
    "# 它提供给我们与众不同的，有创意的一些优化器，包括梯度下降优化器\n",
    "# 替换前面代码相应的行，并且一切工作正常\n",
    "\n",
    "# 设定超参数，Grid Search进行栅格搜索，其实说白了就是排列组合找到Loss Function最小的时刻\n",
    "# 的那组超参数结果\n",
    "n_epochs = 1000\n",
    "learning_rate = 0.001\n",
    "batch_size = 2000\n",
    "\n",
    "# 读取数据，这里读取数据是一下子就把所有数据交给X，Y节点，所以下面去做梯度下降的时候\n",
    "#   BGD = Batch Gradient Decrease ，如果面向数据集比较大的时候，我们倾向与 Mini GD\n",
    "housing = fetch_california_housing(data_home=\"./scikit_learn_data\", download_if_missing=True)\n",
    "\n",
    "m, n = housing.data.shape\n",
    "# 可以使用TensorFlow或者Numpy或者sklearn的StandardScaler去进行归一化\n",
    "X_train, X_test, y_train, y_test = train_test_split(housing.data, housing.target)\n",
    "\n",
    "scaler = StandardScaler().fit(X_train)\n",
    "X_train = scaler.transform(X_train)\n",
    "X_train = np.c_[np.ones((len(X_train), 1)), X_train]\n",
    "X_test = scaler.transform(X_test)\n",
    "X_test = np.c_[np.ones((len(X_test), 1)), X_test]\n",
    "\n",
    "# 下面部分X，Y最后用placeholder可以改成使用Mini BGD\n",
    "# 构建计算的图\n",
    "# X = tf.constant(scaled_housing_data_plus_bias, dtype=tf.float32, name='X')\n",
    "# y = tf.constant(housing.target.reshape(-1, 1), dtype=tf.float32, name='y')\n",
    "X = tf.placeholder(dtype=tf.float32)\n",
    "y = tf.placeholder(dtype=tf.float32)\n",
    "\n",
    "# random_uniform函数创建图里一个节点包含随机数值，给定它的形状和取值范围，就像numpy里面rand()函数\n",
    "theta = tf.Variable(tf.random_uniform([n + 1, 1], -1.0, 1.0), name='theta')\n",
    "y_pred = tf.matmul(X, theta, name=\"predictions\")\n",
    "error = y_pred - y\n",
    "mse = tf.reduce_mean(tf.square(error), name=\"mse\")\n",
    "# 梯度的公式：(y_pred - y) * xj\n",
    "# gradients = 2/m * tf.matmul(tf.transpose(X), error)\n",
    "# gradients = tf.gradients(mse, [theta])[0]\n",
    "# 赋值函数对于BGD来说就是 theta_new = theta - (learning_rate * gradients)\n",
    "# training_op = tf.assign(theta, theta - learning_rate * gradients)\n",
    "\n",
    "# MomentumOptimizer收敛会比梯度下降更快\n",
    "# training_op = tf.train.MomentumOptimizer(learning_rate=learning_rate, momentum=0.9).minimize(mse)\n",
    "training_op = tf.train.GradientDescentOptimizer(learning_rate=learning_rate).minimize(mse)\n",
    "\n",
    "init = tf.global_variables_initializer()\n",
    "\n",
    "# 下面是开始训练\n",
    "with tf.Session() as sess:\n",
    "    sess.run(init)\n",
    "\n",
    "    n_batch = int(len(X_train) / batch_size)\n",
    "\n",
    "    for epoch in range(n_epochs):\n",
    "\n",
    "        if epoch % 100 == 0:\n",
    "            temp_theta = theta.eval()\n",
    "            print(temp_theta)\n",
    "\n",
    "            print(\"Epoch\", epoch, \"MSE = \",\n",
    "                  sess.run(mse, feed_dict={\n",
    "                      X: X_train,\n",
    "                      y: y_train\n",
    "                  }))\n",
    "            print(\"Epoch\", epoch, \"MSE = \",\n",
    "                  sess.run(mse, feed_dict={\n",
    "                      X: X_test,\n",
    "                      y: y_test\n",
    "                  }))\n",
    "\n",
    "        arr = np.arange(len(X_train))\n",
    "        np.random.shuffle(arr)\n",
    "        X_train = X_train[arr]\n",
    "        y_train = y_train[arr]\n",
    "\n",
    "        for i in range(n_batch):\n",
    "            sess.run(training_op, feed_dict={\n",
    "                X: X_train[i*batch_size: i*batch_size + batch_size],\n",
    "                y: y_train[i*batch_size: i*batch_size + batch_size]\n",
    "            })\n",
    "\n",
    "    best_theta = theta.eval()\n",
    "    print(best_theta)\n",
    "\n",
    "# 最后还要进行模型的测试，防止过拟合\n"
   ],
   "id": "f3a1893b633f2ea5",
   "execution_count": 7,
   "outputs": []
  },
  {
   "metadata": {},
   "cell_type": "code",
   "execution_count": null,
   "source": "",
   "id": "6489db8233344a79",
   "outputs": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
